"""
日志工具 - 包含敏感数据过滤
"""
import logging
import re
from typing import Any, Dict, List


class SensitiveDataFilter(logging.Filter):
    """
    敏感数据过滤器
    自动屏蔽日志中的敏感信息
    """
    
    # 敏感字段关键词
    SENSITIVE_KEYS = {
        'password', 'passwd', 'pwd',
        'token', 'access_token', 'refresh_token', 'jwt',
        'secret', 'api_key', 'apikey',
        'authorization', 'auth',
        'credit_card', 'card_number',
        'ssn', 'social_security',
    }
    
    # 敏感数据正则模式
    SENSITIVE_PATTERNS = [
        # JWT Token
        (r'eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}', '***JWT_TOKEN***'),
        # API Key (通常是长字符串)
        (r'\b[A-Za-z0-9]{32,}\b', '***API_KEY***'),
        # 密码字段
        (r'password["\']?\s*[:=]\s*["\']?[^,\s"\']+', 'password=***MASKED***'),
        (r'passwd["\']?\s*[:=]\s*["\']?[^,\s"\']+', 'passwd=***MASKED***'),
        # Token 字段
        (r'token["\']?\s*[:=]\s*["\']?[^,\s"\']+', 'token=***MASKED***'),
    ]
    
    def filter(self, record: logging.LogRecord) -> bool:
        """
        过滤日志记录中的敏感数据
        
        Args:
            record: 日志记录
        
        Returns:
            True（始终返回 True，不阻止日志输出）
        """
        # 处理消息
        if hasattr(record, 'msg') and isinstance(record.msg, str):
            record.msg = self._mask_sensitive_data(record.msg)
        
        # 处理参数
        if hasattr(record, 'args') and record.args:
            if isinstance(record.args, dict):
                record.args = self._mask_dict(record.args)
            elif isinstance(record.args, (list, tuple)):
                record.args = tuple(
                    self._mask_dict(arg) if isinstance(arg, dict) else arg
                    for arg in record.args
                )
        
        return True
    
    def _mask_sensitive_data(self, text: str) -> str:
        """
        屏蔽文本中的敏感数据
        
        Args:
            text: 原始文本
        
        Returns:
            屏蔽后的文本
        """
        if not text:
            return text
        
        # 应用所有敏感数据模式
        for pattern, replacement in self.SENSITIVE_PATTERNS:
            text = re.sub(pattern, replacement, text, flags=re.IGNORECASE)
        
        return text
    
    def _mask_dict(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """
        递归屏蔽字典中的敏感字段
        
        Args:
            data: 原始字典
        
        Returns:
            屏蔽后的字典
        """
        if not isinstance(data, dict):
            return data
        
        masked_data = {}
        for key, value in data.items():
            # 检查键名是否包含敏感关键词
            if any(sensitive_key in key.lower() for sensitive_key in self.SENSITIVE_KEYS):
                masked_data[key] = '***MASKED***'
            elif isinstance(value, dict):
                # 递归处理嵌套字典
                masked_data[key] = self._mask_dict(value)
            elif isinstance(value, list):
                # 处理列表
                masked_data[key] = [
                    self._mask_dict(item) if isinstance(item, dict) else item
                    for item in value
                ]
            elif isinstance(value, str):
                # 屏蔽字符串中的敏感数据
                masked_data[key] = self._mask_sensitive_data(value)
            else:
                masked_data[key] = value
        
        return masked_data
    
    @classmethod
    def mask_token(cls, token: str, show_chars: int = 8) -> str:
        """
        屏蔽 Token，只显示前后几个字符
        
        Args:
            token: 原始 Token
            show_chars: 显示的字符数
        
        Returns:
            屏蔽后的 Token
        """
        if not token or len(token) <= show_chars * 2:
            return '***'
        
        return f"{token[:show_chars]}...{token[-show_chars:]}"


def setup_logging(log_level: str = "INFO"):
    """
    配置日志系统
    
    Args:
        log_level: 日志级别
    """
    # 创建日志格式
    log_format = (
        '%(asctime)s - %(name)s - %(levelname)s - '
        '[%(filename)s:%(lineno)d] - %(message)s'
    )
    
    # 配置根日志记录器
    logging.basicConfig(
        level=getattr(logging, log_level.upper()),
        format=log_format,
        handlers=[
            logging.StreamHandler(),  # 控制台输出
        ]
    )
    
    # 添加敏感数据过滤器到所有处理器
    for handler in logging.root.handlers:
        handler.addFilter(SensitiveDataFilter())
    
    # 配置第三方库的日志级别（避免过多日志）
    logging.getLogger('uvicorn').setLevel(logging.WARNING)
    logging.getLogger('sqlalchemy').setLevel(logging.WARNING)
    logging.getLogger('httpx').setLevel(logging.WARNING)


def get_safe_user_info(user: Any) -> Dict[str, Any]:
    """
    获取安全的用户信息（用于日志）
    
    Args:
        user: 用户对象
    
    Returns:
        安全的用户信息字典
    """
    if not user:
        return {}
    
    return {
        'id': getattr(user, 'id', None),
        'username': getattr(user, 'username', None),
        'role': getattr(user, 'role', None),
        # 不包含 password_hash, email 等敏感信息
    }

